/**
 **************************************************************************************************************************
 * HUB class in charge of making components communicate with each other
 * should contain no behaviour at all
 **************************************************************************************************************************
 * @file RBEntity.h
 **************************************************************************************************************************/

#pragma once

#ifdef  HEADER_MSG
#pragma HEADER_MSG(RBEntity.h)
#endif


/**************************************************************************************************************************
 * Includes
 **************************************************************************************************************************/
#include "RBCommon.h"
#include "RBHandle.h"

/**************************************************************************************************************************
 * Forward declarations
 **************************************************************************************************************************/

/**************************************************************************************************************************
 * Classes
 **************************************************************************************************************************/

RBDeclareHandle(RBEntity);

typedef std::vector<uint16> RBComponentArray ;

class RBEntity
{
public:

    static RBEntityHandle       CreateEntity  ();
    static void                 CreateEntity  (RBEntityHandle* handles, uint32 count=1);
    static void                 DestroyEntity (RBEntityHandle handle);

    static RBEntity&            Get           (RBEntityHandle handle);

    template<class TComponent>
    uint16                      AddComponent    (uint16 handle)                 { return AddComponents(TComponent::GetClassIdx(), &handle, 1); }

    template<class TComponent>
    uint16                      AddComponent    (RBHandle<TComponent> handle)   { return AddComponents(TComponent::GetClassIdx(), &handle.Handle, 1); }

    template<class TComponent>
    uint16                      AddComponents   (uint16* handles, uint32 count) { return AddComponents(TComponent::GetClassIdx(), handles, count); }

    template<class TComponent>
    RBHandle<TComponent>        GetComponent    (uint16 idx) const        { return GetComponent(TComponent::GetClassIdx(), idx); }

    template<class TComponent>
    uint16                      GetComponentCount() const                 { return GetComponentCount(TComponent::GetClassIdx()); }

    template<class TComponent>
    static RBHandle<TComponent> GetComponent (RBEntityHandle handle, uint16 idx) { return RBEntity::Get(handle).GetComponent<TComponent>(idx); }

    template<class TComponent>
    RBHandle<TComponent>        GetComponentByName  (const RBStringID& strName);

    uint16                      AddComponents       (uint32 componentID, uint16* handles, uint32 count);
    uint16                      GetComponent        (uint32 componentID, uint16 idx) const;
    uint16                      GetComponentCount   (uint32 componentID) const;

                               ~RBEntity            ();
private:
                                RBEntity            (RBEntityHandle handle);
    
    RBEntityHandle              m_entity;
    std::vector<RBComponentArray> m_aComponents;

    static std::vector<RBEntity> Instances;
};

template<class TComponent>
RBHandle<TComponent> RBEntity::GetComponentByName( const RBStringID& strName )
{
    RBComponentArray& components = m_aComponents[TComponent::GetClassIdx()];
    for (uint16 ui=0; ui < components.size(); ++ui )
    {
        TComponent& cmp = TComponent::Get(components[ui]);
        if (cmp.Name == strName)
        {
            return components[ui];
        }
    }

    return 0xFFFF;
}
